#pragma once
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <typeindex>
#include <vector>

class Event {
public:
    virtual ~Event() = default;
};

template <typename T>
class EventHandler {
public:
    virtual ~EventHandler() = default;
    virtual void handle(const T& event) = 0;
};

class EventBus {
public:
    static EventBus& instance();

    template <typename T>
    void subscribe(std::shared_ptr<EventHandler<T>> handler);

    template <typename T>
    void unsubscribe(std::shared_ptr<EventHandler<T>> handler);

    template <typename T>
    void publish(const T& event);

    void clear();

private:
    EventBus() = default;
    std::map<std::type_index, std::vector<std::shared_ptr<void>>> handlers_;
    std::mutex mutex_;
};